package com.example.gobang.game;


import com.example.gobang.model.UserInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Component
public class Matcher {
    //    钻石段位
    private Queue<UserInfo> diamondQueue = new LinkedList<>();
    //    星耀段位
    private Queue<UserInfo> startLightQueue = new LinkedList<>();
    // 王者段位
    private Queue<UserInfo> kingQueue = new LinkedList<>();

    @Autowired
    RoomManager roomManager ;

    @Resource(name = "onlineUserManager")
    OnlineUserManager onlineUserManager;

    //   JSON字符串 与 Java对象的转化对象
    ObjectMapper objectMapper = new ObjectMapper();

    // 添加到匹配队列中
    public void add(UserInfo userInfo) {

        /**
         * 为了唤醒 wait
         * 需要给当前对象加锁
         * 并且每添加就notify 唤醒一次
         */

        if (userInfo.getScore() < 2000) {

            synchronized (diamondQueue) {
                // < 2000 为钻石段位
                System.out.println("玩家：" + userInfo.getUserName() + " 进入到匹配队列： diamondQueue");
                diamondQueue.add(userInfo);
                diamondQueue.notify();
            }

        } else if (userInfo.getScore() >= 2000 && userInfo.getScore() < 3000) {
            synchronized (startLightQueue) {

                //            >= 2000 并且 < 3000 为星耀段位
                System.out.println("玩家：" + userInfo.getUserName() + " 进入到匹配队列：startLightQueue");
                startLightQueue.add(userInfo);
                startLightQueue.notify();
            }
        } else {
            synchronized (kingQueue) {

                //            >= 3000 为王者段位
                System.out.println("玩家：" + userInfo.getUserName() + " 进入到匹配队列：kingQueue");
                kingQueue.add(userInfo);
                kingQueue.notify();
            }
        }
    }

    public void remove(UserInfo userInfo) {
        if (userInfo.getScore() < 2000) {
            System.out.println("玩家：" + userInfo.getUserName() + " 出diamondQueue匹配队列");
            diamondQueue.remove(userInfo);
        } else if (userInfo.getScore() >= 2000 && userInfo.getScore() < 3000) {
            System.out.println("玩家：" + userInfo.getUserName() + " 出startLightQueue匹配队列");
            startLightQueue.remove(userInfo);
        } else {
            System.out.println("玩家：" + userInfo.getUserName() + " 出kingQueue匹配队列");
            kingQueue.remove(userInfo);
        }
    }


    public Matcher() {
        // 1. 给每个匹配队列分配线程
        Thread t1 = new Thread(() -> {
            // 开始扫描钻石匹配队列
            while (true) {
                matchHandler(diamondQueue);
            }
        });

//        开启线程
        t1.start();
        Thread t2 = new Thread(() -> {
            // 开始扫描星耀匹配队列
            while (true) {
                matchHandler(startLightQueue);
            }
        });


        Thread t3 = new Thread(() -> {
//            开始扫描王者匹配队列
            while (true) {
                matchHandler(kingQueue);
            }
        });


    }

    private void matchHandler(Queue<UserInfo> matchQueue) {
        try {

            // 1. 首先第一步加锁
            synchronized (matchQueue) {
                // 2. 判断队列的个数是否 = 0 或 1 的情况
                while (matchQueue.size() < 2) {
//                循环判断， 防止出现只有 0 个再添加的情况的情况
                    matchQueue.wait();
                }

//                3. 出队列获取到对象方便获取对应的
                UserInfo player1 = matchQueue.poll();
                UserInfo player2 = matchQueue.poll();


                // 4. 从在线状态中获取session 会话来给客户端发送成功匹配的响应并且特判
                WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());

                // 5.  特判
                if (session1 == null) {
//                        如果用户1 不在线就返回用户 2 即可
                    matchQueue.offer(player2);
                    System.out.println("[matchHandler]:: player1未登录!");
                    return;
                }

                if (session2 == null) {
//                        如果用户2 不在线就返回用户1 即可
                    matchQueue.offer(player1);
                    System.out.println("[matchHandler]:: player2未登录!");
                    return;
                }

                if (session1 == session2) {
                    /**
                     * 如果这两个会话相同 ， 说明同一个玩家加入了队列两次
                     * 这里就需要只返回一个玩家
                     * 然后退出扫描
                     */
                    matchQueue.offer(player1);
                    System.out.println("[matchHandler]:: player1 和 和 player2 是同一账号!");

                    return;
                }

                // 5. 将这两个玩家加入到同一个房间进行管理
                Room room = new Room();

                System.out.println("玩家一: " + player1.getUserName() + ", 玩家二: " + player2.getUserName() + "匹配到同一房间成功!!");
                roomManager.add(room, player1.getUserId(), player2.getUserId());

                // 6. 匹配成功发回辉各自客户端
                MatchResponse response1 = new MatchResponse();
                response1.setMessage("successMatch");
                response1.setOk(true);
                session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response1)));

                MatchResponse response2 = new MatchResponse();
                response2.setOk(true);
                response2.setMessage("successMatch");

                session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response2)));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
